package com.colt.contentcenter.config.rule;

import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.ribbon.NacosServer;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.client.naming.core.Balancer;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.BaseLoadBalancer;
import com.netflix.loadbalancer.Server;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @program: content-center
 * @description: Ribbon配置同一集群优先调用
 * 步骤：找出指定服务的所有实例A
 * 找出同一集群下的所有实例B
 * 若B为空，就在A实例中进行选择
 * 采用基于权重的负载均衡算法，返回一个实例
 * @author: colt
 * @create: 2020-05-06 09:38
 **/
@Slf4j
public class NacosSameClusterWeightedRule extends AbstractLoadBalancerRule {
    @Autowired
    NacosDiscoveryProperties nacosDiscoveryProperties;
    @Override
    public void initWithNiwsConfig(IClientConfig iClientConfig) {

    }

    @Override
    public Server choose(Object key) {
        try {
        //首先获取本地集群的名字
        String localClusterName = nacosDiscoveryProperties.getClusterName();
        BaseLoadBalancer loadBalancer = (BaseLoadBalancer) this.getLoadBalancer();
        //log.info("loadBalancer:{}", loadBalancer);
        loadBalancer.getName();//想要请求微服务的名称
        //拿到服务发现的相关API
        NamingService namingService = nacosDiscoveryProperties.namingServiceInstance();


            List<Instance> sameCluster = new ArrayList<>();
            List<Instance> unsameCluster = new ArrayList<>();
            //获取所有健康的实例
            List<Instance> AllInstances = namingService.selectInstances("user-center", true);
            List<Instance> sameClusterInstances = AllInstances.stream()
                    .filter(instance -> { return Objects.equals(instance.getClusterName(), localClusterName); })
                    .collect(Collectors.toList());
            //选取的合集
            List<Instance> choosenClusterInstance = new ArrayList<>();
            if (CollectionUtils.isEmpty(sameClusterInstances)){
                choosenClusterInstance = AllInstances;
                log.warn("发生跨集群调用：name = {},clusterName = {},instance = {}",namingService,localClusterName,AllInstances);
            }else {
                choosenClusterInstance = sameClusterInstances;
                log.info("调用本地集群：name = {},clusterName = {},instance = {}",namingService,localClusterName,AllInstances);
            }
            Instance instance = ExtendBalancer.getHostByRandomWeight2(choosenClusterInstance);
            log.info("选择的实例:{},端口:{}",instance,instance.getPort());
            return new NacosServer(instance);
        } catch (NacosException e) {
            log.info("猜猜发生了什么：{}",e);
            e.printStackTrace();
            return null;
        }

    }
}

class ExtendBalancer extends Balancer{
    public static Instance getHostByRandomWeight2(List<Instance> hosts){
        return getHostByRandomWeight(hosts);
    }
}
